package com.linmu.service.impl;

import com.linmu.config.MyLoginLimitConfig;
import com.linmu.entity.User;
import com.linmu.mapper.UserMapper;
import com.linmu.service.UserService;
import com.linmu.utils.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("UserService")
public class UserServiceImpl implements UserService {

    final MyLoginLimitConfig loginLimitConfig;
    final UserMapper userMapper;
    final RedisUtil redisUtil;

    @Autowired
    public UserServiceImpl(UserMapper userMapper, RedisUtil redisUtil, MyLoginLimitConfig loginLimitConfig) {
        this.userMapper = userMapper;
        this.redisUtil = redisUtil;
        this.loginLimitConfig = loginLimitConfig;
    }

    /**
     * 根据用户名到mysql数据库中查找用户
     * @param username 用户名
     * @return 用户类
     */
    @Override
    public User GetUserByUsername(String username) {
        return userMapper.GetUserByUsername(username);
    }

    /**
     * 更新用户信息到mysql数据库
     * @param newUser 新的用户类
     * @return 更新是否成功
     */
    @Override
    public boolean UpdateUser(User newUser) {
        //更新数据库
        userMapper.UpdateUser(newUser);
        //获取数据库中的当前用户数据
        User user = GetUserByUsername(newUser.getUsername());
        //对比是否相等（User类被@Data注解，由lombok重写了equal方法。）
        return user.equals(newUser);
    }

    /**
     * 登录
     * @param username 用户名
     * @param password 密码
     * @return 用户类
     */
    @Override
    public User login(String username, String password) {
        //通过用户名获取对应用户信息
        User userReal = GetUserByUsername(username);

        //判断用户名是否存在 并 进行密码校验
        if(userReal!=null && userReal.getPassword().equals(password)) {
            return userReal;
        }
        else {
            setFailCount(username);
            int count = getUserFailCount(username);
            if(count == loginLimitConfig.getTimesFailToLock()) {
                //设置锁定
                String lockKey = "user:"+username+":lockTime";
                redisUtil.set(lockKey,"1",loginLimitConfig.getLockTime());
                //清空错误累计
                String key = "user:"+username+":failCount";
                redisUtil.del(key);
            }
            return null;
        }

    }

    /**
     * 获取用户账户锁定时间
     * @param username 用户名
     * @return 锁定时间（未锁定为-1）
     */
    @Override
    public long getUserLoginLockTime(String username) {
        String key = "user:" + username + ":lockTime";
        long lockTime = redisUtil.getExpireSeconds(key);
        if(lockTime > 0) {
            return lockTime;
        }
        else {
            return -1;
        }
    }

    /**
     * 设置登录失败次数
     * @param username  用户名
     * @return  是否成功
     */
    @Override
    public boolean setFailCount(String username) {
        try {
            long count = getUserFailCount(username);
            String key = "user:" + username + ":failCount";
            if(count < 0){//判断redis中是否有该用户的失败登陆次数。
                redisUtil.set(key,1, loginLimitConfig.getConstFailTime());
            }else{
                redisUtil.incr(key, 1.0);
            }
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }

    }

    /**
     * 获取登录失败次数
     * @param username 用户名
     * @return 失败次数（没有记录则为-1）
     */
    @Override
    public int getUserFailCount(String username) {
        String key = "user:" + username + ":failCount";
        //从redis中获取当前用户已失败次数
        Object object = redisUtil.get(key);
        if(object != null){
            return (int)object;
        }else{
            return -1;
        }
    }

}
